package com.leshua.channel.mpos.service.pay.impl;

import com.leshua.channel.mpos.common.utils.LeshuaXmlUtils;
import com.leshua.channel.mpos.model.lepos.Merchant;
import com.leshua.channel.mpos.service.lepos.MerchantService;
import com.leshua.channel.mpos.service.mpos.MposAgentWhiteService;
import com.leshua.channel.mpos.service.pay.ScanPayService;
import com.leshua.channel.mpos.service.remote.ScanPayRemoteService;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.yeahka.commons.utils.MD5;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author devlin
 * @version 1.0
 * @date 2020/4/24 15:00
 */
@Service
@Slf4j
public class ScanPayServiceImpl implements ScanPayService {

    private final static Pattern UNDERLINE_PATTERN = Pattern.compile("([A-Za-z\\d]+)(_)?");

    @Resource
    private ScanPayRemoteService scanPayRemoteService;

    @Resource
    private MposAgentWhiteService agentWhiteService;

    @Resource
    private MerchantService merchantService;


    @Override
    public void handle(ChannelHandlerContext ctx, String msg) {
        if (msg.length() < 10) {
            log.info("无效的请求参数！{}", msg);
            ctx.writeAndFlush(Unpooled.copiedBuffer(LeshuaXmlUtils.errorMsg("无效的请求"), CharsetUtil.UTF_8));
            return;
        }
        String industryCode = msg.substring(3, 9);
        System.out.println(industryCode);
        String tradeData = msg.substring(9);
        Map<String, String> paramsMap = new TreeMap<>();
        Map<String, String> requestMap = new HashMap<>();
        for (String keyValue : tradeData.split("&")) {
            String[] param = keyValue.split("=");
            if (param.length == 2) {
                paramsMap.put(param[0], param[1]);
                requestMap.put(underlineToCamel(param[0], true), param[1]);
            }
        }
        String sign = paramsMap.get("sign");
        System.out.println(tradeData);
        boolean result = checkSign(requestMap, sign);
        log.info("签名结果：{}", result);
        boolean canPay = checkCanScanPay(requestMap.get("merchantId"));
        log.info("交易白名单检查结果：{}", canPay);
        String serverName = paramsMap.get("service");
        String returnMsg = "";
        if ("get_tdcode".equalsIgnoreCase(serverName)) {
            returnMsg = getTdCode(requestMap);
        } else if ("query_status".equalsIgnoreCase(serverName)) {
            returnMsg = queryStatus(requestMap);
        } else {
            returnMsg = LeshuaXmlUtils.errorMsg("无效的方法！");
        }
        log.info(returnMsg);
        ctx.writeAndFlush(Unpooled.copiedBuffer(returnMsg, CharsetUtil.UTF_8));
    }

    /**
     * 查看是否可以进行扫码交易
     *
     * @return
     */
    private boolean checkCanScanPay(String merchantId) {
        return agentWhiteService.canScanPay(merchantId);
    }


    private String getTdCode(Map<String, String> paramsMap) {
        String result = scanPayRemoteService.posTwoDimensionalCode(paramsMap);
        log.info("拉取二维码：{}", result);
        return result;
    }


    private String queryStatus(Map<String, String> paramsMap) {
        String result = scanPayRemoteService.posQueryResult(paramsMap);
        log.info("查询扫码交易结果：{}", result);
        return result;
    }


    public boolean checkSign(Map<String, String> params, String sign) {
        String stringSignTemp = "";
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if ("sign".equalsIgnoreCase(entry.getKey())) {
                continue;
            }
            stringSignTemp += "&" + entry.getKey() + "=" + entry.getValue();
        }
        Merchant merchant = merchantService.queryMerchant(params.get("merchantId"));

        String signKey = merchant.getBindMerchantKey();
        //去掉头部的&
        stringSignTemp = stringSignTemp.substring(1) + "&key=" + signKey;
        log.info("final signTemp: {}", stringSignTemp);

        if (MD5.md5(stringSignTemp).equalsIgnoreCase(sign)) {
            return true;
        }
        log.info("签名错误，请求可能被篡改！");
        return false;
    }


    /**
     * 下划线转驼峰法
     *
     * @param line       源字符串
     * @param smallCamel 大小驼峰,是否为小驼峰
     * @return 转换后的字符串
     */
    public String underlineToCamel(String line, boolean smallCamel) {
        if (line == null || "".equals(line)) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        Matcher matcher = UNDERLINE_PATTERN.matcher(line);
        while (matcher.find()) {
            String word = matcher.group();
            sb.append(smallCamel && matcher.start() == 0 ? Character.toLowerCase(word.charAt(0)) : Character.toUpperCase(word.charAt(0)));
            int index = word.lastIndexOf('_');
            if (index > 0) {
                sb.append(word.substring(1, index).toLowerCase());
            } else {
                sb.append(word.substring(1).toLowerCase());
            }
        }
        return sb.toString();
    }
}
